/******************************************************************************
** $Id: imgbuffer.h,v 1.1 2009-04-22 18:44:06 rayskymy Exp $
**                 Proprietary and Confidential Information                  **
**                                                                           **
**                Copyright (c) 2002-2005 Oasis Semiconductor Inc.           **
**                                                                           **
**  This software contains proprietary and confidential material which is    **
**  property of Oasis Semiconductor Inc.                                     **
**                                                                           **
******************************************************************************/
#ifndef _imgbuffer_h_
# define _imgbuffer_h_
/**************************************************************************//**
*  @file imgbuffer.h
*  @brief This file contains the definition of the IMGBUFFER.  An IMGBUFFER
*  is an image container to describe a contiguous region of memory.
*
*  This file contains the definition of the IMGBUFFER structure as well as 
*  useful API calls to use the IMGBUFFER.
******************************************************************************/
/******************************************************************************
*  FILE FORMAT: <PUBLIC>
*      1. INCLUDES 
*      2. ENUMERATIONS 
*      3. DEFINES
*      4. STRUCTURES
*      5. GLOBALS
*      6. PUBLIC FUNCTION PROTOTYPES
******************************************************************************/
/******************************************************************************
*  1. INCLUDES
******************************************************************************/
/*
** This define should not be enabled in source control.  It should only be
** defined locally for debugging.
*/
//# define IMGBUFFER_DEBUG

# ifdef WIN32
#  undef IMGBUFFER_DEBUG
# endif /* ifdef WIN32 */

# if SDK_VERSION < 3
#  include "type.h"
# endif /* if SDK_VERSION < 3 */

# ifdef IMGBUFFER_DEBUG
#  include "os.h"
# endif /* ifdef IMGBUFFER_DEBUG */

/******************************************************************************
*  2. ENUMERATIONS
******************************************************************************/
/******************************************************************************
*  3. DEFINES
******************************************************************************/
/******************************************************************************
*  4. STRUCTURES
******************************************************************************/
/**
** @brief Image Buffer: Controls the sharing of raw image data
** 
** An IMGBUFFER is a standard way to share a contiguous block of memory. There
** are several firmware modules who require a provider/consumer interface to
** share a contiguous section of memory. The IMGBUFFER is a standard way to
** provide a data flow between different firmware modules. The construct provides
** a standard method of performing per scanline flow control and does not touch
** the image data itself. Image data is exchanged through the use of a shared
** memory buffer. For instance, an IMGBUFFER is the output of the IDU (Image
** Decompression Unit) to the SGU (Swath Generator Unit). In this case, the IDU
** is the provider of uncompressed data to the SGU to consume this data for
** printing on an ink-based system.
**
** The IMGBUFFER interface facilitates this sharing of memory through a data
** structure and series of inline functions for the provider and consumer.
*/
typedef struct IMG_BUFFER_STRUCT {
    /**
    ** A standard DigiColor buffer attribute. Defines the base address of the 
    ** buffer shared memory buffer.
    */
    UINT32 base;

    /**
    ** A standard DigiColor buffer attribute. Defines the memory increment in 
    ** bytes required to move from the beginning of scanline (n) to the beginning
    ** of scanline (n+1).
    */
    UINT32 stride;

    /**
    ** A standard DigiColor buffer attribute. Defines the size of the buffer in 
    ** scanlines. Please note that the size of the buffer is actually (ySize + 1).
    */
    UINT32 ySize;

    /**
    ** This variable indicates the position within the buffer at which the provider
    ** will deposit the next scanline. 
    ** Tracks the buffer read and write pointers. Range: [0,ySize]. yProvider is
    ** initialized to the yStart value during the call to IMGBUF_Init(...). It
    ** can be queried via the IMGBUF_ReportConsumerY functions. It will be updated
    ** as scanlines are provided/consumed via the IMGBUF_ProvideScanlines and 
    ** IMGBUF_ConsumeScanlines functions.
    */
    UINT32 yProvider;

    /**
    ** This variable indicates the location from which the consumer will remove the
    ** next scanline. 
    ** Tracks the buffer read and write pointers. Range: [0,ySize]. yProvider is
    ** initialized to the yStart value during the call to IMGBUF_Init(...). It
    ** can be queried via the IMGBUF_ReportConsumerY functions. It will be updated
    ** as scanlines are provided/consumed via the IMGBUF_ProvideScanlines and 
    ** IMGBUF_ConsumeScanlines functions.
    */
    UINT32 yConsumer; 

    /**
    ** Indicates the location from which yProvider and yConsumer have started on
    ** the call of IMGBUF_Init(). This is never changed.
    */
    UINT32 yStart;

    /**
    ** Tracks the total number of scanlines provided to the buffer (ie. written).
    ** The functions
    ** IMGBUF_ReportEmptyScanlines and IMGBUF_ReportValidScanlines use this 
    ** variable to provide flow control support.  The variable will be 
    ** updated as scanlines are provided via the IMGBUF_ProvideScanlines function. 
    */
    UINT32 scanlinesProvided;

    /**
    ** Track the total number of scanlines consumed from the buffer (ie. read).  
    ** The functions
    ** IMGBUF_ReportEmptyScanlines and IMGBUF_ReportValidScanlines use this 
    ** variable to provide flow control support.  The variable will be 
    ** updated as scanlines are consumed via the IMGBUF_ConsumeScanlines function.
    */
    UINT32 scanlinesConsumed;

    /**
    ** Maintain valid scanlines in the buffer which have been already resided
    ** by another provider and have not been comsumed yet 
    ** at the time of initialization.  The number of scanlinesPreOccupied
    ** can be decremented to 0 by calling IMGBUF_PrevOccupiedScanlines.
    **/
    UINT32 scanlinesPrevOccupied;

    /** 
    ** Number of channels used for the image.  This is primarily used to aid the
    ** consumer.
    */
    UINT8 numberOfChannels;

    /**
    ** Number of bits per pixel.  Can be one of [1..8].
    */
    UINT8 numberOfBitsPerPixel;

    /**
    ** A IMGBUFFER may contain several channels of one image. Height of one channel 
    ** of the image.
    */
    UINT32 imageHeight;

    /**
    ** A IMGBUFFER may contain several channels of one image. Width of one channel 
    ** of the image.
    */
    UINT32 imageWidth;
} IMGBUFFER, *pIMGBUFFER;
/******************************************************************************
*  5. GLOBALS
******************************************************************************/
/******************************************************************************
*  6. PUBLIC FUNCTION PROTOTYPES
******************************************************************************/

/**************************************************************************//**
*  An image buffer must be initialized prior to use.  An agent must define 
*  the shared memory buffer attributes (base, stride, ySize) and the scanline
*  position within the buffer at which the first scanline to be transferred 
*  should be placed.  Note that depending on the situation, the provider or
*  consumer of the image buffer may also act as the initializer.
*  
*  @param i - Pointer to IMGBUFFER.
*  @param base - Base address of IMGBUFFER.
*  @param stride - Stride of IMGBUFFER.
*  @param ySize - Height of IMGBUFFER-1.
*  @param yStart - Starting pointer of IMGBUFFER.
******************************************************************************/
INLINE void IMGBUF_Init (IMGBUFFER *i, 
                         UINT32 base, 
                         UINT32 stride, 
                         UINT32 ySize, 
                         UINT32 yStart)
{	
    i->base = base;
    i->ySize = ySize;
    i->stride = stride;
    i->yProvider = i->yConsumer = i->yStart = yStart;
    i->scanlinesProvided = 0;
    i->scanlinesConsumed = 0;
    i->scanlinesPrevOccupied = 0;
}

/**************************************************************************//**
*  This routine will only initialize the base of the given IMGBUFFER.
*  
*  @param i - Pointer to IMGBUFFER.
*  @param base - Base address of IMGBUFFER.
******************************************************************************/
INLINE void IMGBUF_InitBase (pIMGBUFFER i, UINT32 base)
{	
    i->base = base;
}

/**************************************************************************//**
*  This routine will only initialize the starting height location of the given 
*  IMGBUFFER.
*  
*  @param i - Pointer to IMGBUFFER.
*  @param ySize - Starting pointer of IMGBUFFER.
******************************************************************************/
INLINE void IMGBUF_InitYStart (IMGBUFFER *i, UINT32 yStart)
{	
    i->yProvider = i->yConsumer = i->yStart = yStart;
}

/**************************************************************************//**
*  This routine will set the number of the scanlines that has been resided 
*  in the memory buffer at initialization. It's possible to be called after
*  initialization.
*  IMGBUFFER.
*  
*  @param i - Pointer to IMGBUFFER.
*  @param n - Number of scanlines to set
******************************************************************************/
INLINE void IMGBUF_PrevOccupiedScanlines (IMGBUFFER *i, UINT32 n)
{	
    if (n <= i->ySize)
      i->scanlinesPrevOccupied = n;
}

/**************************************************************************//**
*  The provider will periodically deposit scanlines into the image buffer.  
*  Before depositing scanlines, the provider should use the EmptyScanlines()
*  function to determine the number of empty scanlines, and thus the number of
*  scanlines which can be added (provided) to the buffer.
*  
*  @param i - Pointer to IMGBUFFER.
*
*  @return Returns number of scanlines available in the IMGBUFFER.
******************************************************************************/
INLINE UINT32 IMGBUF_EmptyScanlines (IMGBUFFER *i)
{
    //return(i->ySize + 1 - (i->scanlinesProvided - i->scanlinesConsumed));
    return(i->ySize + 1 - i->scanlinesPrevOccupied - (i->scanlinesProvided - i->scanlinesConsumed));
}

/**************************************************************************//**
*  The provider reports that scanlines have been added by calling the 
*  ProvideScanlines function.  The number of scanlines should not exceed
*  the size of the buffer!
*  
*  @param i - Pointer to IMGBUFFER.
*  @param n - Number of scanlines to provide.
******************************************************************************/
INLINE void IMGBUF_ProvideScanlines (IMGBUFFER *i, UINT32 n)
{
    if (!n) return;

# ifdef IMGBUFFER_DEBUG
    if (n > i->ySize+1) {
        OSRUN_PrintLine('*');
        OSRUN_Dpf("IMGBUF ERROR!");
        OSRUN_Dpf("PROV %d > %d", n, i->ySize);
        OSRUN_PrintLine('*');
        return;
    }
# endif

    i->scanlinesProvided += n;
    while (n--) {
        if (i->yProvider == i->ySize)
            i->yProvider = 0;
        else
            i->yProvider += 1;
    }
}

/**************************************************************************//**
*  The consumer will periodically remove scanlines from the image buffer.  
*  Before removing scanlines, the provider should use the ValidScanlines()
*  function to determine the number of valid scanlines, and thus the number of
*  scanlines which can be removed (consumed) from the buffer.
*  
*  @param i - Pointer to IMGBUFFER.
******************************************************************************/
INLINE UINT32 IMGBUF_ValidScanlines (IMGBUFFER *i)
{
    return(i->scanlinesProvided - i->scanlinesConsumed);
}

/**************************************************************************//**
*  The consumer reports that scanlines have been removed by calling the 
*  ConsumeScanlines function.  The number of scanlines to consume should not
*  exceed the size of the buffer!
*  
*  @param i - Pointer to IMGBUFFER.
*  @param n - Number of scanlines to consume.
******************************************************************************/
INLINE void IMGBUF_ConsumeScanlines (IMGBUFFER *i, UINT32 n)
{
    if (!n) return;

    i->scanlinesConsumed += n;

# ifdef IMGBUFFER_DEBUG
    if (n > i->ySize+1) {
        OSRUN_PrintLine('*');
        OSRUN_Dpf("IMGBUF ERROR!");
        OSRUN_Dpf("CONS %d > %d", n, i->ySize);
        OSRUN_PrintLine('*');
        return;
    }
# endif

    while (n--) {
        if (i->yConsumer == i->ySize)
            i->yConsumer = 0;
        else
            i->yConsumer += 1;
    }
}

/**************************************************************************//**
*  Provides the total number of valid scanlines. Used for flow control. 
*  
*  @param i - Pointer to IMGBUFFER.
*
*  @return Returns the total number of scanlines provided since the IMGBUFFER
*  was intialized.
******************************************************************************/
INLINE UINT32 IMGBUF_ReportValidScanlines (IMGBUFFER *i)
{
    return (i->scanlinesProvided);
}

/**************************************************************************//**
*  Provides the total number of empty scanlines. Used for flow control. 
*  
*  @param i - Pointer to IMGBUFFER.
*
*  @return Returns the total number of scanlines consumed since the IMGBUFFER
*  was intialized.
******************************************************************************/
INLINE UINT32 IMGBUF_ReportEmptyScanlines (IMGBUFFER *i)
{
    return (i->scanlinesConsumed);
}

/**************************************************************************//**
*  Retrieve the starting height of the IMGBUFFER set at initialization.
*  
*  @param i - Pointer to IMGBUFFER.
*
*  @return Returns the starting height of the IMGBUFFER.
******************************************************************************/
INLINE UINT32 IMGBUF_ReportYStart (IMGBUFFER *i)
{
    return (i->yStart);
}

/**************************************************************************//**
*  Retrieve the current pointer used by the provider.
*  
*  @param i - Pointer to IMGBUFFER.
*
*  @return Returns the current provider location in the IMGBUFFER.
******************************************************************************/
INLINE UINT32 IMGBUF_ReportProviderY (IMGBUFFER *i)
{
    return (i->yProvider);
}

/**************************************************************************//**
*  Retrieve the current consumer used by the provider.
*  
*  @param i - Pointer to IMGBUFFER.
*
*  @return Returns the current consumer location in the IMGBUFFER.
******************************************************************************/
INLINE UINT32 IMGBUF_ReportConsumerY (IMGBUFFER *i)
{
    return (i->yConsumer);
}

/**************************************************************************//**
*  Dump the given IMGBUFFER to the trace log. This is just a debugging 
*  function.
*  
*  @param imgbufferP - Pointer to IMGBUFFER.
******************************************************************************/
void IMGBUF_Display(volatile IMGBUFFER *imgBufferP);
#endif /*  _imgbuffer_h_ */
